package com.wanfajie.smsdistribute.ui.phone_group_content

import android.app.Service
import android.content.ClipData
import android.content.ClipboardManager
import android.content.DialogInterface
import android.content.Intent
import android.os.Bundle
import android.support.design.widget.BaseTransientBottomBar
import android.support.design.widget.Snackbar
import android.support.v7.app.AppCompatActivity
import android.support.v7.view.ActionMode
import android.support.v7.widget.DividerItemDecoration
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.OrientationHelper
import android.support.v7.widget.SearchView
import android.text.SpannableString
import android.text.style.ForegroundColorSpan
import android.util.Log
import android.view.ContextMenu
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.TextView
import com.wanfajie.smsdistribute.R
import com.wanfajie.smsdistribute.common.activity.BaseActivity
import com.wanfajie.smsdistribute.common.adapter.CheckedRecyclerAdapter.CheckedViewHolder
import com.wanfajie.smsdistribute.common.adapter.SearchRecyclerAdapter
import com.wanfajie.smsdistribute.common.adapter.SlideLeadRecyclerAdapter
import com.wanfajie.smsdistribute.db.bean.phone.PhoneGroup
import com.wanfajie.smsdistribute.db.bean.phone.PhoneNumber
import com.wanfajie.smsdistribute.db.quietInvoke
import com.wanfajie.smsdistribute.db.repository.impl.GroupRepositoryImpl
import com.wanfajie.smsdistribute.ui.contacts_picker.ContactsPickerActivity
import com.wanfajie.smsdistribute.util.confirm
import com.wanfajie.smsdistribute.util.pinyinInitial
import com.wanfajie.smsdistribute.util.toast
import kotlinx.android.synthetic.main.activity_group_content.*
import java.sql.SQLException

class PhoneGroupContentActivity: BaseActivity() {

    companion object {
        const val EXTRA_KEY = "group_id"
        private const val TAG = "PhoneGroupContent"
    }

    private lateinit var mPhoneGroup: PhoneGroup
    private var mLastClick: PhoneNumber? = null
    private var mSearchView: SearchView? = null
    private var mActionSearchView: SearchView? = null
    private var mSearchStr: String = ""
        set(v) {
            if (v == field) return
            field = v
            val query = if (v == "") null else v
            mSearchView?.setQuery(query, false)
            mActionSearchView?.setQuery(query, false)

            mSearchView?.isIconified = v.isEmpty()
            mActionSearchView?.isIconified = v.isEmpty()
        }

    private val mAdapter: SlideLeadRecyclerAdapter<PhoneNumber> by lazy {
        object : SlideLeadRecyclerAdapter<PhoneNumber>(this,
                mPhoneGroup.phoneNumbers ?: emptyList(),
                R.layout.list_item_phone_number, R.id.checkbox,
                R.id.lead, View.GONE, { it.name }
        ) {
            init {
                setItemCheckable(false)
                setOnLongClickListener {
                    if (!isItemCheckable()) {
                        startSupportActionMode(mActionModeCb)
                        false
                    } else {
                        finishActionMode()
                        true
                    }
                }
                setOnClickListener {
                    val vh = it.tag as CheckedViewHolder
                    mLastClick = vh.tag as PhoneNumber

                    if (!isItemCheckable())
                        it.showContextMenu()
                }
            }

            override fun processViewHolder(p0: CheckedViewHolder, p1: PhoneNumber) {
                super.processViewHolder(p0, p1)
                p0.get<TextView>(R.id.item_name).text = p1.name
                p0.get<TextView>(R.id.item_small_name).text = p1.getNumber()
            }
        }
    }

    private val mSearchAdapter: SearchRecyclerAdapter<PhoneNumber, CheckedViewHolder> by lazy {
        object : SearchRecyclerAdapter<PhoneNumber, CheckedViewHolder>(
                mAdapter, { ForegroundColorSpan(resources.getColor(android.R.color.holo_red_light)) },
                arrayOf(R.id.item_name, R.id.item_small_name)
        ) {

            override fun filter(index: Int, item: PhoneNumber): Boolean {
                return keyword.isEmpty()
                        || item.name.contains(keyword, ignoreCase = true)
                        || item.getNumber().contains(keyword, ignoreCase = true)
                        || item.name.pinyinInitial.contains(keyword, ignoreCase = true)
            }

            override fun highlight(str: CharSequence): SpannableString {
                return highlight(str, SearchRecyclerAdapter.HIGHLIGHT_HANYU_INDEX_GENE)
            }
        }
    }

    private val mActionModeCb by lazy {
        object: ActionMode.Callback {

            override fun onActionItemClicked(p0: ActionMode?, p1: MenuItem?): Boolean {
                return when (p1?.itemId) {
                    android.R.id.selectAll -> {
                        mAdapter.all(!mAdapter.isCheckedAll())
                        true
                    }
                    R.id.delete -> {
                        val checkedItems = mAdapter.getCheckedItemList()
                        confirm(this@PhoneGroupContentActivity,
                                R.string.delete,
                                getString(R.string.confirm_delete_checked_items_count, checkedItems.size),
                                R.string.delete) { _, witch ->

                            if (witch != DialogInterface.BUTTON_POSITIVE) return@confirm

                            val deleted = checkedItems.filter {
                                quietInvoke(TAG, false, SQLException::class) {
                                    it.delete() > 0
                                }
                            }

                            if (deleted.isNotEmpty()) {
                                mAdapter.removeAll(deleted)
                                toast(strId = R.string.successfully_deleted)
                            }

                            if (deleted.size != checkedItems.size) {
                                val failure = checkedItems.toMutableList()
                                failure.removeAll(deleted)
                                Log.w(TAG, "删除失败 ${failure.size} 条: $failure")
                            }

                            mAdapter.setItemCheckable(false)
                            p0?.finish()
                        }
                        true
                    }
                    else -> false
                }
            }

            override fun onCreateActionMode(p0: ActionMode?, p1: Menu?): Boolean {
                menuInflater.inflate(R.menu.menu_group_content_action_mode, p1)
                mActionSearchView = p1?.findItem(R.id.action_search)?.actionView as SearchView?
                mActionSearchView?.let {
                    processSearchMenuItem(it)
                }
                return true
            }

            override fun onDestroyActionMode(p0: ActionMode?) {
                mAdapter.setItemCheckable(false)
                mActionSearchView = null
            }

            override fun onPrepareActionMode(p0: ActionMode?, p1: Menu?): Boolean = false
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if (intent.extras == null) {
            finish()
            return
        }

        val group = GroupRepositoryImpl.findById(intent.extras.getInt(EXTRA_KEY))
        if (group == null) {
            finish()
            return
        }
        setContentView(R.layout.activity_group_content)

        mPhoneGroup = group
        supportActionBar?.title = group.groupName
        supportActionBar?.setDisplayHomeAsUpEnabled(true)

        phone_list.addItemDecoration(DividerItemDecoration(this, OrientationHelper.VERTICAL))
        phone_list.layoutManager = LinearLayoutManager(this).apply {
            orientation = OrientationHelper.VERTICAL
        }
        phone_list.adapter = mSearchAdapter
        registerForContextMenu(phone_list)

        slide_index.setTextViewDialog(slide_index_dialog)
        slide_index.setOnItemSlideListener(mAdapter)
    }

    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        menuInflater.inflate(R.menu.menu_group_content, menu)
        val searchItem = menu?.findItem(R.id.search)
        mSearchView = searchItem?.actionView as SearchView?
        mSearchView?.let {
            processSearchMenuItem(it)
        }
        return true
    }

    private fun processSearchMenuItem(searchView: SearchView) {
        searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
            override fun onQueryTextChange(p0: String?): Boolean = false

            override fun onQueryTextSubmit(p0: String?): Boolean {
                val kw = p0 ?: ""
                mSearchAdapter.search(kw)
                mAdapter.isShowLead = kw.isEmpty()
                mSearchStr = kw
                return true
            }
        })

        searchView.setOnCloseListener {
            mSearchAdapter.search("")
            mAdapter.isShowLead = true
            slide_index.visibility = View.VISIBLE
            mSearchStr = ""
            false
        }

        searchView.setOnSearchClickListener {
            slide_index.visibility = View.GONE
        }

        searchView.setQuery(mSearchStr, true)
        if (mSearchStr.isNotEmpty()) {
            searchView.setIconifiedByDefault(true)
            searchView.isFocusable = true
            searchView.isIconified = false
            searchView.requestFocusFromTouch()
        }
    }

    override fun onOptionsItemSelected(item: MenuItem?): Boolean {
        return when (item?.itemId) {
            android.R.id.home -> {
                finish()
                true
            }
            R.id.pick_contacts -> {
                val intent = Intent(this, ContactsPickerActivity::class.java)
                startActivityForResult(intent, 1122)
                true
            }
            R.id.add -> {
                // TODO: 添加电话号码
                true
            }
            R.id.rename -> {
                val title = getString(R.string.rename)

                EditDialog(this, title) {
                    if (it.isEmpty() || it.isBlank()) {

                        val msg = getString(
                            R.string.cannot_be_empty,
                            getString(R.string.group_name)
                        )

                        toast(msg)
                        return@EditDialog
                    }

                    mPhoneGroup.groupName = it
                    if (GroupRepositoryImpl.updateGroup(mPhoneGroup)) {
                        supportActionBar?.title = it
                        toast(strId = R.string.successfully_modified)
                    } else {
                        val msg = getString(R.string.modified_failure_already_exists, it)
                        toast(msg)
                    }
                }.setText(mPhoneGroup.groupName)
                        .show()

                true
            }
            R.id.delete -> {
                confirm(this, R.string.delete,
                        getString(R.string.confirm_delete_group, mPhoneGroup.groupName),
                        R.string.delete) { _, witch ->

                    if (witch != DialogInterface.BUTTON_POSITIVE) return@confirm

                    if (GroupRepositoryImpl.removeGroup(mPhoneGroup)) {
                        toast(strId = R.string.successfully_deleted)
                        finish()
                    } else {
                        toast(strId = R.string.delete_failure)
                    }
                }
                true
            }
            else -> super.onOptionsItemSelected(item)
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if (requestCode == 100) {
            val number = mLastClick ?: return
            val newNumber = number.dao.queryForSameId(number)
            val index = mAdapter.indexOf(number)
            mAdapter.remove(number)
            mAdapter.add(newNumber, index)
            return
        }

        if (resultCode == AppCompatActivity.RESULT_CANCELED) return

        if (requestCode == 1122) {
            val names = data?.extras?.getStringArrayList(ContactsPickerActivity.EXTRA_KEY_NAME)
            val numbers = data?.extras?.getStringArrayList(ContactsPickerActivity.EXTRA_KEY_NUMBER)

            names?.mapIndexed { index, s ->
                val number = numbers!![index].replace(" ", "")
                PhoneNumber.create(s, number, mPhoneGroup)
            }?.filterNotNull()?.let {
                mAdapter.addAll(0, it)
            }
        }
    }

    private val mClipManager: ClipboardManager by lazy {
        getSystemService(Service.CLIPBOARD_SERVICE) as ClipboardManager
    }

    override fun onContextItemSelected(item: MenuItem?): Boolean {
        val number = mLastClick ?: return false
        val index = mAdapter.indexOf(number)

        return when (item?.itemId) {
            R.id.copy_name -> {
                val data = ClipData.newPlainText("text", number.name)
                mClipManager.primaryClip = data
                toast(strId = R.string.successful_copy)
                true
            }
            R.id.copy_phone_number -> {
                val data = ClipData.newPlainText("text", number.getNumber())
                mClipManager.primaryClip = data
                toast(strId = R.string.successful_copy)
                true
            }
            R.id.delete -> {
                mAdapter.remove(number)
                val msg = getString(R.string.deleted_item, number.name)

                Snackbar.make(phone_list, msg, 10000).setAction(R.string.undo) {
                    mAdapter.add(number, index)
                }.addCallback(object : BaseTransientBottomBar.BaseCallback<Snackbar>() {

                    override fun onDismissed(transientBottomBar: Snackbar?, event: Int) {
                        super.onDismissed(transientBottomBar, event)
                        // 不是因为点击撤销而消失就删除
                        if (event != BaseTransientBottomBar.BaseCallback.DISMISS_EVENT_ACTION) {
                            number.delete()
                        }
                    }
                }).show()
                true
            }
            R.id.edit -> {
                PhoneDetailActivity.startActivity(this, number, requestCode = 100)
                true
            }
            else -> super.onContextItemSelected(item)
        }
    }

    override fun onCreateContextMenu(menu: ContextMenu?, v: View?, menuInfo: ContextMenu.ContextMenuInfo?) {
        menuInflater.inflate(R.menu.menu_group_item_context, menu)
        mLastClick?.let {
            menu?.setHeaderTitle(it.name)
        }
    }

    override fun onBackPressed() {
        when {
            mSearchView?.isIconified == false -> mSearchView?.isIconified = true
            mActionSearchView?.isIconified == false -> mActionSearchView?.isIconified = true
            else -> super.onBackPressed()
        }
    }
}